/*
 * Copyright 2008 Zoundry LLC, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 */
package org.zoundry.gaedt.ui.builders.providers;

import java.io.InputStream;
import java.io.StringReader;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.xml.sax.InputSource;
import org.zoundry.gaedt.core.ZGaeException;
import org.zoundry.gaedt.core.codegen.ZGaeCSpecToPythonGenerator;
import org.zoundry.gaedt.core.models.cspec.ZGaeCSpecReader;
import org.zoundry.gaedt.core.models.cspec.ZGaeControllersModel;
import org.zoundry.gaedt.core.util.ZGaeResourceUtil;
import org.zoundry.gaedt.core.util.ZGaeUTF8Util;
import org.zoundry.gaedt.ui.builders.IZGaeBuildProvider;


/**
 * A build provider for a .cspec file.
 */
public class ZGaeCSpecBuildProvider implements IZGaeBuildProvider
{
    /**
     * C'tor.
     */
    public ZGaeCSpecBuildProvider()
    {
    }

    /**
     * @see org.zoundry.gaedt.ui.builders.IZGaeBuildProvider#accept(org.eclipse.core.resources.IResource)
     */
    public boolean accept(IResource aResource)
    {
        return aResource.getType() == IResource.FILE && "cspec".equalsIgnoreCase(aResource.getFileExtension());
    }

    /**
     * @see org.zoundry.gaedt.ui.builders.IZGaeBuildProvider#build(org.eclipse.core.resources.IResource)
     */
    public void build(IResource aResource) throws ZGaeException
    {
        // TODO need to do validation of the .cspec file and generate problem markers (schema validation)
        try
        {
            IFile file = getDerivedPythonFile(aResource);
            if (shouldBuild(aResource, file))
            {
                String fileContents = ZGaeResourceUtil.getContents((IFile) aResource);
                ZGaeCSpecReader reader = ZGaeCSpecReader.getInstance();
                InputSource iSource = new InputSource(new StringReader(fileContents));
                ZGaeControllersModel cspecModel = (ZGaeControllersModel) reader.read(iSource);
                String pythonCode = generatePythonCodeFromCSpec(cspecModel);
                InputStream inputStream = ZGaeUTF8Util.getInputStream(pythonCode);
                if (file.exists())
                    file.setContents(inputStream, true, true, null);
                else
                    file.create(inputStream, true, null);
            }
        }
        catch (Throwable t)
        {
            throw new ZGaeException(t);
        }
    }

    /**
     * Returns true if the python file should be generated.
     *
     * @param aCSpecResource
     * @param aPyFile
     */
    protected boolean shouldBuild(IResource aCSpecResource, IFile aPyFile)
    {
        if (!aCSpecResource.exists() || !(aCSpecResource.getType() == IResource.FILE))
            return false;
        if (!aPyFile.exists())
            return true;

        long cspecTimestamp = aCSpecResource.getLocalTimeStamp();
        long pyTimestamp = aPyFile.getLocalTimeStamp();

        return pyTimestamp < cspecTimestamp;
    }

    /**
     * Generate Python code from the given .cspec.
     *
     * @param aCSpecModel
     */
    private String generatePythonCodeFromCSpec(ZGaeControllersModel aCSpecModel)
    {
        ZGaeCSpecToPythonGenerator generator = new ZGaeCSpecToPythonGenerator();
        return generator.generate(aCSpecModel);
    }

    /**
     * Given the resource, get an {@link IFile} for the generated python output.
     *
     * @param aResource
     */
    private IFile getDerivedPythonFile(IResource aResource)
    {
        IProject project = aResource.getProject();
        String resourceName = aResource.getName();
        String baseName = resourceName.substring(0, resourceName.lastIndexOf('.'));
        String pyName = baseName + ".py";
        IPath pyPath = aResource.getParent().getProjectRelativePath().append(pyName);
        IFile pyFile = project.getFile(pyPath);
        try
        {
            pyFile.setDerived(true);
        }
        catch (CoreException e)
        {
        }
        return pyFile;
    }

    /**
     * @see org.zoundry.gaedt.ui.builders.IZGaeBuildProvider#removeBuild(org.eclipse.core.resources.IResource)
     */
    public void removeBuild(IResource aResource) throws ZGaeException
    {
        try
        {
            IFile derivedPythonFile = getDerivedPythonFile(aResource);
            if (derivedPythonFile.exists() && derivedPythonFile.isDerived())
                derivedPythonFile.delete(true, null);
        }
        catch (CoreException e)
        {
            throw new ZGaeException(e);
        }
    }
}
